package com.xiaoyung.easyisapisdk.common.util;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.util.ParameterizedTypeImpl;
import com.xiaoyung.easyisapisdk.common.base.PageList;

import feign.Response;
import feign.Util;
import feign.codec.Decoder;

public class ObjectDecoder implements  Decoder {
	private static Logger logger = LoggerFactory.getLogger(ObjectDecoder.class);
	private boolean camleNameModel;
	public ObjectDecoder(boolean camleNameModel) {
		this.camleNameModel = camleNameModel;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public Object decode(Response response, Type type) throws IOException {
		Response.Body body = response.body();
		if (body == null) {
			return null;
		}

		String result = Util.toString(body.asReader(Util.UTF_8));
		
		Method method = response.request().requestTemplate().methodMetadata().method();
		logger.debug("result:"+result);
		
		// create_time //下划线转驼峰
		boolean isJSONObject = result==null?false: result.startsWith("{");
		boolean isJSONArray = result==null? false: result.startsWith("[");
		Object jsonRet = null;
		if(isJSONObject||isJSONArray) {
			jsonRet = JSON.parse(result);
		}
		if(isJSONObject) {
			//logger.debug("====result 是JSONObject类型=====");
			JSONObject jsonObjRet = (JSONObject)jsonRet;
			
			if(jsonObjRet.containsKey("code") && jsonObjRet.containsKey("msg")) {//出错情况下 data可能没有 && ret.containsKey("data")
				//标准结构 rest restTable
				Integer code = jsonObjRet.getInteger("code");
				String msg = jsonObjRet.getString("msg");
				if(code!=200) {
					throw new ApiException(code,msg);
				}
				
				Object retData = jsonObjRet.get("data");//Integer JSONObject String JOSNArray Boolean
				
				if (retData == null || method.getReturnType() == Void.class) {
					return null;// 无返回值 Void 情况
				}
				if(retData instanceof JSONObject || retData instanceof JSONArray) {
					//array || object
					if(retData instanceof JSONObject) {
						//logger.debug("retData 是JSONObject类型");
						JSONObject rowsData = ((JSONObject) retData);
						Object listObj = rowsData.get("list");
						if(rowsData.containsKey("list") && listObj instanceof JSONArray) {
							//logger.debug("retData 含有list 是分页信息");
							//JSONArray list = (JSONArray)listObj;
							//&& rowsData.containsKey("total");
							//.getJSONArray("list");
							Class<?> returnItemType = com.xiaoyung.easyisapisdk.common.util.ReflectUtils.getReturnTypeGenericArgument(method);
							
							PageList<Object> page = (PageList<Object>) PageList.buildPage(rowsData,returnItemType ,camleNameModel);
							return page;
						}
					}
					
					if(JSON.class.isAssignableFrom(method.getReturnType())) {
						//logger.debug("returnType 是json直接返回");
						return retData;
					}
					
					// camleNameModel
					if(Map.class.isAssignableFrom(method.getReturnType())) {
						//logger.debug("returnType 是map直接jsonObj转map返回");
						//如果getReturnType 是map类型或者map的子类
						try {
							Map<String,Object> newMap = ((Map<String,Object>)(method.getReturnType().newInstance()));
							if(!(retData instanceof JSONObject)) {
								throw new RuntimeException("retData不是JSONObject类型请检查");
							}
							newMap.putAll((JSONObject)retData);
							//logger.debug("怎么会没有返回呢?== {}",JSONUtils.objectToJsonString(newMap));

							return newMap;
							/*if(retData instanceof Map) {
								return newMap;
							}else {
								throw new RuntimeException("类型不匹配 method returnType和返回类型 不是map无法转换");
							}*/
						} catch (InstantiationException  | IllegalAccessException e) {
							throw new RuntimeException(e);
						}
						
					}else if(List.class.isAssignableFrom(method.getReturnType())) {
						//logger.debug("returnType 是list直接jsonArray转List<Entity>返回");
						Type[] genericReturnTypes = ((ParameterizedType)(method.getGenericReturnType())).getActualTypeArguments();
						Class<?> genericParameterClass = (Class<?>)genericReturnTypes[0];
						//list 或者
						List<Object> list = new ArrayList<>();
						JSONArray arr = (JSONArray)retData;
						for (int i = 0; i < arr.size(); i++) {
							JSONObject obj = arr.getJSONObject(i);
							if(obj!=null) {
								Object entity = null;
								//logger.debug("returnType 是List<T> T是:"+genericParameterClass.getSimpleName()+" 转List<Entity>");
								entity = JSON.to(genericParameterClass,obj);
								list.add(entity);
							}
						}
						return list;
					}else {
						//bean对象类型
						try {
							//Object bean = method.getReturnType().getConstructor().newInstance();
							Class<?> returnClass = method.getReturnType();
							Object entity = JSON.to(returnClass,retData);
							return entity;
						} catch (Exception e) {
							if(e instanceof RuntimeException) {
								throw (RuntimeException)e;
							}else {
								throw new RuntimeException(e);
							}
						}
					}
				}else {
					//number string boolean
					return retData;
				}
			}
			/*	Type actualType = ((ParameterizedType) type).getActualTypeArguments()[0];
				logger.debug("result: "+data);
				ret = JSON.parseObject(data,buildType(type,actualType));
					
				if(ret instanceof Rest) {
					Rest<?> r =((Rest<?>)ret);
					if(r.getCode()!=200) {
						throw new ApiException(r.getMsg());
					}
				}else if(ret instanceof RestTable) {
					RestTable<?> r =((RestTable<?>)ret);
					if(r.getCode()!=200) {
						throw new ApiException(r.getMsg());
					}
				}
				return ret;*/
		}else if(isJSONArray){
			//logger.debug("====result 是JSONArray类型=====");
			JSONArray jsonArrayRet = (JSONArray)jsonRet;
			return JSON.to(method.getReturnType(),jsonArrayRet);
		}else {
			//logger.debug("====result 是简单值类型=====");
			if (method.getReturnType() == Integer.class) {
				return StringUtils.isEmpty(result) ? null : Integer.valueOf(result);
			}else if(method.getReturnType()==Long.class) {
				return StringUtils.isEmpty(result) ? null : Long.valueOf(result);
			}else if(method.getReturnType()==Boolean.class) {
				return StringUtils.isEmpty(result) ? null : Boolean.valueOf(result);
			}else if (method.getReturnType() == Date.class) {
				//暂时没这个类型
				//返回字符串2025-01-01 11:11:11
				//返回时间戳
				//return StringUtils.isEmpty(data) ? null : new Date(Long.valueOf(data));
			}else if (method.getReturnType() == Void.class) {
				return null;
			}
		}
		//logger.debug("都没有匹配到 最终返回String");
		return result;
		//jsonobject类型并且有data属性则去除包裹只返回data
		/*if(data.startsWith("{")) {
			JSONObject ret = JSON.parseObject(data);
			if(ret.containsKey("data")) {
				return JSONPath.read(data, "data", method.getReturnType());
			}
		}*/
		
		//根据返回类型来
		/*if(type == JSONObject.class) {
			return JSON.parse(data);
		}else if(type instanceof ParameterizedType) {
			
			Type actualType = ((ParameterizedType) type).getActualTypeArguments()[0];
			logger.debug("result: "+data);
			Object ret = JSON.parseObject(data,buildType(type,actualType));
			if(ret instanceof Rest) {
				Rest<?> r =((Rest<?>)ret);
				if(r.getCode()!=200) {
					throw new ApiException(r.getMsg());
				}
			}else if(ret instanceof RestTable) {
				RestTable<?> r =((RestTable<?>)ret);
				if(r.getCode()!=200) {
					throw new ApiException(r.getMsg());
				}
			}
			return ret;
		}
		
		return data;*/
		
		/* if (String.class.equals(type)) {
		  return Util.toString(body.asReader(Util.UTF_8));
		}
		throw new DecodeException(response.status(),
		    format("%s is not a type supported by this decoder.", type), response.request());*/
	}
	public static ParameterizedTypeImpl buildType(Type... types) {
		ParameterizedTypeImpl type = null;
		for (int i = types.length - 1; i > 0; i--) {
			type = new ParameterizedTypeImpl(new Type[] { type == null ? types[i] : type }, null, types[i - 1]);
		}
		return type;
	}
}